package spring.cloud.tasks.executor.trigger;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import spring.cloud.tasks.executor.task.TaskExecuteEngine;

import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

@Slf4j
@Setter
@Getter
public class Scheduler {

    private static final String SATURN_QUARTZ_WORKER = "-Worker";
    private final TaskExecuteEngine taskExecuteEngine;
    private final ExecutorService executorService;
    private Trigger trigger;
    private Worker worker;

    public Scheduler(final TaskExecuteEngine taskExecuteEngine, final Trigger trigger) {
        this.taskExecuteEngine = taskExecuteEngine;
        this.trigger = trigger;
        executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {//
            @Override
            public Thread newThread(Runnable runnable) {
                Thread thread = new Thread(runnable, taskExecuteEngine.getExecutorId() + "_" + taskExecuteEngine.getTaskConfigurationService().getTaskId() + SATURN_QUARTZ_WORKER);
                thread.setDaemon(false);
                thread.setPriority(Thread.NORM_PRIORITY);
                return thread;
            }
        });
    }

    public void start() {
        worker = new Worker(taskExecuteEngine, trigger.createTriggered(false), trigger.createQuartzTrigger());
        if (trigger.isInitialTriggered()) {
            trigger();
        }
        executorService.submit(worker);
    }

    public Trigger getTrigger() {
        return trigger;
    }

    public void shutdown() {
        worker.halt();
        executorService.shutdown();
    }

    public boolean isTerminated() {
        return executorService.isTerminated();
    }

    public void awaitTermination(long timeout) {
        try {
            executorService.awaitTermination(timeout, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    public void trigger() {
        worker.trigger(trigger.createTriggered(true));
    }

    public boolean isShutdown() {
        return worker.isShutDown();
    }

    public void reInitializeTrigger() {
        worker.reInitTrigger(trigger.createQuartzTrigger());
    }

    public Date getNextFireTimePausePeriodEffected() {
        return worker.getNextFireTimePausePeriodEffected();
    }
}
